/*
 * Copyright 2012 Faculty of Informatics - Masaryk University.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cz.muni.fi.pa165.creatures.services.impl;

import cz.muni.fi.pa165.creatures.dao.CreatureTypeDAO;
import cz.muni.fi.pa165.creatures.dao.CreatureTypeWeaponDAO;
import cz.muni.fi.pa165.creatures.dao.WeaponDAO;
import cz.muni.fi.pa165.creatures.dao.exceptions.WeaponEffectivityException;
import cz.muni.fi.pa165.creatures.dto.CreatureTypeDTO;
import cz.muni.fi.pa165.creatures.dto.CreatureTypeWeaponDTO;
import cz.muni.fi.pa165.creatures.dto.WeaponDTO;
import cz.muni.fi.pa165.creatures.dto.mapping.CreatureTypeMapping;
import cz.muni.fi.pa165.creatures.dto.mapping.CreatureTypeWeaponMapping;
import cz.muni.fi.pa165.creatures.dto.mapping.WeaponMapping;
import cz.muni.fi.pa165.creatures.model.CreatureType;
import cz.muni.fi.pa165.creatures.model.CreatureTypeWeapon;
import cz.muni.fi.pa165.creatures.model.Weapon;
import cz.muni.fi.pa165.creatures.services.EffectivityService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * This class represents the implementation of
 * {@link cz.muni.fi.pa165.creatures.services.EffectivityService}.
 *
 * @author xvojtis2
 */
@Service
public final class EffectivityServiceImpl implements EffectivityService {

    private static final Logger logger =
            Logger.getLogger(EffectivityServiceImpl.class.getName());
    
    @Autowired
    private CreatureTypeMapping creatureTypeMapping;
    
    @Autowired
    private WeaponMapping weaponMapping;
    
    @Autowired
    private CreatureTypeWeaponDAO creatureTypeWeaponDAO;
    
    @Autowired
    private CreatureTypeDAO creatureTypeDAO;
    
    @Autowired
    private WeaponDAO weaponDAO;
    
    @Autowired
    private CreatureTypeWeaponMapping creatureTypeWeaponMapping;

    @Override
    @Transactional
    public void addEffectivity(final CreatureTypeDTO creatureType,
            final WeaponDTO weaponDTO, final Float effectivity)
            throws WeaponEffectivityException {
        if (getCountOfEffectivitiesByCreatureType(
                creatureTypeMapping.DTOtoEntity(creatureType).getId())
                >= MAX_WEAPONS_OF_CREATURE_TYPE) {
            throw new WeaponEffectivityException(
                    "There are already >= " + MAX_WEAPONS_OF_CREATURE_TYPE
                    + " weapons assigned to "
                    + "creatureType= " + creatureType.toString());
        }

        try {
            CreatureType creatureTypeDB = creatureTypeDAO.get(Long.parseLong(creatureType.getId()));
            Weapon weaponDB = weaponDAO.get(Long.parseLong(weaponDTO.getId()));

            CreatureTypeWeapon creatureTypeWeapon = new CreatureTypeWeapon();

            creatureTypeWeapon.setEffectivity(effectivity);
            creatureTypeWeapon.setCreatureType(creatureTypeDB);
            creatureTypeWeapon.setWeapon(weaponDB);
            creatureTypeWeaponDAO.create(creatureTypeWeapon);

        } catch (DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }

    @Override
    @Transactional
    public void removeEffectivity(final CreatureTypeDTO creatureType,
            final WeaponDTO weaponDTO) {
        try {
            CreatureTypeWeapon creatureTypeWeapon = creatureTypeWeaponDAO
                    .get(creatureTypeMapping.DTOtoEntity(creatureType),
                    weaponMapping.DTOtoEntity(weaponDTO));
            if (creatureTypeWeapon != null) {
                creatureTypeWeaponDAO.remove(creatureTypeWeapon);
            }
        } catch (DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }

    @Override
    public void removeAllEffectivities(WeaponDTO weaponDTO) {
        try {
            Weapon weapon = weaponDAO.get(weaponMapping.DTOtoEntity(weaponDTO).getId());
            List<CreatureTypeWeapon> ctwList = creatureTypeWeaponDAO.getAll();
            for (CreatureTypeWeapon ctw : ctwList) {
                if (ctw.getWeapon().getId().equals(weapon.getId())) {
                    creatureTypeWeaponDAO.remove(ctw);
                }
            }
        } catch(DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }    
    
    @Override
    @Transactional
    public void removeEffectivity(Long creatureTypeId, Long weaponId) {
        try {
            CreatureType creatureTypeDB = creatureTypeDAO.get(creatureTypeId);
            Weapon weaponDB = weaponDAO.get(weaponId);
            CreatureTypeWeapon creatureTypeWeapon = creatureTypeWeaponDAO
                    .get(creatureTypeDB, weaponDB);
            if (creatureTypeWeapon != null) {
                creatureTypeWeaponDAO.remove(creatureTypeWeapon);
            }
        } catch (DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }

    @Override
    @Transactional
    public void updateEffectivity(final CreatureTypeDTO creatureType,
            final WeaponDTO weaponDTO, final Float effectivity) {
        try {
            CreatureTypeWeapon creatureTypeWeapon = new CreatureTypeWeapon();
            creatureTypeWeapon
                    .setCreatureType(creatureTypeMapping
                    .DTOtoEntity(creatureType));

            creatureTypeWeapon.setWeapon(weaponMapping.DTOtoEntity(weaponDTO));
            creatureTypeWeapon.setEffectivity(effectivity);

            creatureTypeWeaponDAO.update(creatureTypeWeapon);

        } catch (DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }

    @Override
    @Transactional
    public List<CreatureTypeWeaponDTO> getAllByCreatureType(Long id) {
        try {
            CreatureType creatureTypeDB = creatureTypeDAO.get(id);
            List<CreatureTypeWeapon> ctw = creatureTypeWeaponDAO.getAll();

            List<CreatureTypeWeaponDTO> ctwDTO = new ArrayList<CreatureTypeWeaponDTO>();
            for (CreatureTypeWeapon creatureTypeWeapon : ctw) {
                if (creatureTypeWeapon.getCreatureType().equals(creatureTypeDB)) {
                    ctwDTO.add(creatureTypeWeaponMapping.entityToDTO(creatureTypeWeapon));
                }
            }
            return ctwDTO;
        } catch (DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }

    @Override
    @Transactional
    public Integer getCountOfEffectivitiesByCreatureType(Long creatureTypeId) {
        try {
            CreatureType creatureTypeDB = creatureTypeDAO.get(creatureTypeId);
             List<CreatureTypeWeapon> ctw = creatureTypeWeaponDAO.getAll();

            Integer counter = 0;
            for (CreatureTypeWeapon creatureTypeWeapon : ctw) {
                if (creatureTypeWeapon.getCreatureType().equals(creatureTypeDB)) {
                    counter++;
                }
            }
            return counter;

        } catch (DataAccessException ex) {
            logger.log(Level.INFO, ex.getMessage());
            throw ex;
        }
    }
}